﻿using EquipSecs300;
using log4net.Util;
using SecsEquip;
using SecsEquip300;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EquipSecs300
{
    public class GEM_RemoteContro : SecsEquipEx
    {
        public string m_pViewName;
        public event Action<object, RemoteCommandHandlerEventArgs> onRemoteCommandEventHandler = null;

        public event Func<REMOTE_REPLY_KE> SeClearAlarm = null;
        public event Func<REMOTE_REPLY_KE> SeClearCounter = null;
        public event Func<REMOTE_REPLY_KE> SePause = null;
        public event Func<REMOTE_REPLY_KE> SeResume = null;
        public event Func<REMOTE_REPLY_KE> SeStop = null;
        public event Func<string, REMOTE_REPLY_KE> SeAcceptCassette = null;
        public event Func<string, REMOTE_REPLY_KE> SeRejectCassette = null;
        public event Func<string, string, string, string, REMOTE_REPLY_KE> SeAcceptWafer = null;
        public event Func<REMOTE_REPLY_KE> SeRejectWafer = null;
        public event Func<string, string, string, REMOTE_REPLY_KE> SeSelectPPID = null;
        public event Func<string, REMOTE_REPLY_KE> SeStart = null;
        public event OnPJobCreateHandler m_pPJobCreateProc = null;
        public event OnCJobCreateHandler m_pCJobCreateProc = null;
        public event OnCMSCarrierSlotMapStatusChangeHandler m_pCMSCarrierSlotMapStatusChange = null;
        public event Func<string, List<string>> SeGetWaferIDList = null;

        public GEM_RemoteContro(CSecsEquip300 m_pSecs, SecsEquipHelper secsEquipHelper)
        {
            this.m_pSecs = m_pSecs;
            this.SecsEquipHelper = secsEquipHelper;
        }

        public override void UpdateData()
        {
            //m_pSecs.m_pOnRemoteCommand += OnRemoteCommandEventHandler;
            m_pSecs.m_pOnRemoteExCommand += OnRemoteCommandEventHandlerActive;

        }

        #region
        // 远程控制:SKD主动调用返回RemoteCmdReply
        REMOTE_REPLY OnRemoteCommandEventHandler(object sender, RemoteCommandHandlerEventArgs e)
        {
            onRemoteCommandEventHandler?.Invoke(sender, e);
            switch (e.pCMD)
            {
                case "START":
                    {
                        // 调用开始作业命令
                        // RunStart();
                    }
                    break;
                case "PAUSE":
                    {

                    }
                    break;
                case "RESUME":
                    {

                    }
                    break;
                case "STOP":
                    {

                    }
                    break;
                case "PP-SELECT":
                    return HandlePPSelect(e);

                case "LIST-CMD"://s2f49
                    {
                        // 参数名称 param1
                        //
                        // 参数值是list类型
                        //  L:3
                        //      L:2
                        //          A POCKETID
                        //          A VALUE
                        //      L:2
                        //          A TX
                        //          A VALUE
                        //      L:2
                        //          A TEST1
                        //          A VALUE

                        try
                        {
                            string pValue = e.mapParament["param1"];
                            List<string> listLevel1 = new List<string>();    // 层1 
                            CListOperate.listSplit(pValue, ref listLevel1);

                            if (listLevel1.Count != 4)
                            {
                                // 个数不等于4                              
                                return REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;    // 参数不满足要求
                            }

                            // 提取参数和参数名称
                            // 第一个参数
                            string pPOCKETIDNameAndValue = listLevel1[1];
                            string pPOCKETID = CListOperate.listElement(pPOCKETIDNameAndValue, 1);      // 提取list中的位置1的数据，位置从0开始算 0，1，2...
                            string pPOCKETIDValue = CListOperate.listElement(pPOCKETIDNameAndValue, 2);      // 提取list中的位置1的数据
                            pPOCKETID = CListOperate.listElement(pPOCKETIDNameAndValue, 1);     // 提取值数据,去掉类型
                            pPOCKETIDValue = CListOperate.listElement(pPOCKETIDValue, 1);       // 提取值数据,去掉类型

                            // 提取参数和参数名称
                            // 第二个参数
                            string pTXNameAndValue = listLevel1[2];
                            string pTX = CListOperate.listElement(pTXNameAndValue, 1);      // 提取list中的位置1的数据
                            string pTXValue = CListOperate.listElement(pTXNameAndValue, 2);      // 提取list中的位置1的数据
                            pTX = CListOperate.listElement(pTX, 1);                     // 提取值数据,去掉类型
                            pTXValue = CListOperate.listElement(pTXValue, 1);            // 提取值数据,去掉类型

                            // 提取参数和参数名称
                            // 第三个参数
                            string pTEST1NameAndValue = listLevel1[3];
                            string pTEST1 = CListOperate.listElement(pTXNameAndValue, 1);      // 提取list中的位置1的数据
                            string pTEST1Value = CListOperate.listElement(pTXNameAndValue, 2);      // 提取list中的位置1的数据
                            pTEST1 = CListOperate.listElement(pTEST1, 1);                       // 提取值数据,去掉类型
                            pTEST1Value = CListOperate.listElement(pTEST1Value, 1);             // 提取值数据,去掉类型

                        }
                        catch (System.Exception)
                        {
                        }
                    }
                    break;

                case "其他命令处理":
                    break;

                // 命令不存在
                default:
                    return REMOTE_REPLY.eCOMMAND_NOT_EXIST;
            }


            return REMOTE_REPLY.eCOMMAND_PERFORMED;
        }
        #endregion


        // 远程控制：用户主动调用返回RemoteCmdReply
        void OnRemoteCommandEventHandlerActive(object sender, RemoteCommandHandlerEventArgs e)
        {
            REMOTE_REPLY reply = REMOTE_REPLY.eCOMMAND_REJECTED;
            if (GlobalVar.EAPRemote)
            {
                try
                {
                    onRemoteCommandEventHandler?.Invoke(sender, e);
                    switch (e.pCMD)
                    {
                        case "CLRALM": //Clear Alarm报警清除
                            {
                                SeClearAlarm?.Invoke();
                                reply = REMOTE_REPLY.eCOMMAND_PERFORMED;
                            }
                            break;
                        case "ACCCST": //Accept Cassette接受当前卡匣，Robot可以进行取放Wafer
                        case "9100":
                            {
                                reply = HandleAcceptFoupPoupLoad(e);
                            }
                            break;
                        case "REJCST": //Reject Cassette拒绝当前卡匣，直接Unload卡匣
                        case "9101":
                            {
                                reply = HandleRejectFoupPoupLoad(e);
                            }
                            break;
                        case "ACCWAF": //Accept Wafer接受当前Wafer，可以进行3D检测
                        case "9110":
                            {
                                reply = HandleAcceptWaferID(e);
                            }
                            break;
                        case "REJWAF": //Reject Wafer拒绝当前Wafer，放回到卡匣中
                        case "9111":
                            {
                                SeRejectWafer?.Invoke();
                                reply = REMOTE_REPLY.eCOMMAND_PERFORMED;
                            }
                            break;
                        case "PPSELECT": //Select PPID设定当前使用的Recipe
                        case "9115":
                            {
                                reply = HandlePPSelect(e);
                            }
                            break;
                        case "START": //Start设定结束，可以进行取放Wafer
                        case "9116":
                            {
                                reply = HandleStartFoupPoupLoad(e);
                            }
                            break;
                        case "PAUSE":
                            {
                                SePause?.Invoke();
                                reply = REMOTE_REPLY.eCOMMAND_PERFORMED;
                            }
                            break;
                        case "RESUME":
                            {
                                SeResume?.Invoke();
                                reply = REMOTE_REPLY.eCOMMAND_PERFORMED;
                            }
                            break;
                        case "STOP":
                            {
                                SeStop?.Invoke();
                                reply = REMOTE_REPLY.eCOMMAND_PERFORMED;
                            }
                            break;
                        // 命令不存在
                        default:
                            {
                                reply = REMOTE_REPLY.eCOMMAND_NOT_EXIST;
                                break;
                            }
                    }

                    LogCommMsg(e);
                }
                catch (Exception ex)
                {
                    // 异常情况
                    reply = REMOTE_REPLY.eCOMMAND_OTHER;
                    LogRemoteMsg($"ERR -> {ex.Message}");
                }
            }

            m_pSecs.RemoteCmdReply(e.pReplyMailbox, reply);

        }


        REMOTE_REPLY HandlePPSelect(RemoteCommandHandlerEventArgs e)
        {
            REMOTE_REPLY reMote = REMOTE_REPLY.eCOMMAND_PERFORMED;
            try
            {
                if (!e.mapParament.ContainsKey("PPID") || !e.mapParament.ContainsKey("LOTNO") || !e.mapParament.ContainsKey("PORTNO"))
                {
                    e.listErrorCode.Add(new CodeDescription(1, "Recipe Parament Not Exist"));
                    reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                    return reMote;
                }
                string pRecipeName = e.mapParament["PPID"];   // 提取名称
                string pLotName = e.mapParament["LOTNO"];
                string pPortName = e.mapParament["PORTNO"];

                if (false)//改为使用PJob,CJob方式
                {
                    reMote = (REMOTE_REPLY)SeSelectPPID.Invoke(pPortName, pRecipeName, pLotName);
                }

                ProcessJob pJob = null;
                ControlJob cJob = null;
                if (SecsDataHelper.Function.RecipeNameSource == "RemoteComm")
                {
                    pJob = CreatePJob(pPortName, pRecipeName, pLotName);
                    if (pJob != null)
                    {
                        m_pPJobCreateProc?.Invoke(this, pJob);
                        LogRemoteMsg("PJobInfo创建成功！！");
                    }
                    cJob = CreateCJob(pJob, pPortName);
                    if (cJob != null)
                    {
                        m_pCJobCreateProc?.Invoke(this, cJob);
                        LogRemoteMsg("CJobInfo创建成功！！");
                    }
                }

                Carrier carrier = null;
                if (SecsDataHelper.Function.CarrierInfoSource == "RemoteComm")
                {
                    carrier = CreateCarrierInfo(pPortName, pLotName);

                    if (carrier != null)
                    {
                        m_pCMSCarrierSlotMapStatusChange?.Invoke(this, UtilitiesConvert.StringToInt32(pPortName), carrier);
                        LogRemoteMsg("CarrierInfo创建成功！！");
                    }
                }

                if (pJob != null && cJob != null && carrier != null)
                {
                    reMote = REMOTE_REPLY.eCOMMAND_PERFORMED;
                }
                else
                {
                    reMote = REMOTE_REPLY.eCOMMAND_OTHER;
                }

            }
            catch (System.Exception ex)
            {
                // 不存在Recipe存在，Host没有发送过来
                reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                LogRemoteMsg($"ERR -> {ex.Message}");
            }
            return reMote;
        }

        REMOTE_REPLY HandleAcceptFoupPoupLoad(RemoteCommandHandlerEventArgs e)
        {
            REMOTE_REPLY reMote = REMOTE_REPLY.eCOMMAND_PERFORMED;
            try
            {
                if (!e.mapParament.ContainsKey("ACCCST"))
                {
                    e.listErrorCode.Add(new CodeDescription(1, "PortID Not Exist"));
                    reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                    return reMote;
                }
                string pPortName = e.mapParament["ACCCST"];   // 提取名称
                REMOTE_REPLY_KE rt = SeAcceptCassette.Invoke(pPortName);
                reMote = (REMOTE_REPLY)rt;
            }
            catch (System.Exception ex)
            {
                // 不存在
                reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                LogRemoteMsg($"ERR -> {ex.Message}");
            }
            return reMote;
        }

        REMOTE_REPLY HandleRejectFoupPoupLoad(RemoteCommandHandlerEventArgs e)
        {
            REMOTE_REPLY reMote = REMOTE_REPLY.eCOMMAND_PERFORMED;
            try
            {
                if (!e.mapParament.ContainsKey("REJCST"))
                {
                    e.listErrorCode.Add(new CodeDescription(1, "Command Not Exist"));
                    reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                    return reMote;
                }
                string pPortName = e.mapParament["REJCST"];   // 提取名称
                REMOTE_REPLY_KE rt = SeRejectCassette.Invoke(pPortName);
                reMote = (REMOTE_REPLY)rt;
            }
            catch (System.Exception ex)
            {
                // 不存在
                reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                LogRemoteMsg($"ERR -> {ex.Message}");
            }
            return reMote;
        }


        REMOTE_REPLY HandleStartFoupPoupLoad(RemoteCommandHandlerEventArgs e)
        {
            REMOTE_REPLY reMote = REMOTE_REPLY.eCOMMAND_PERFORMED;
            try
            {
                if (!e.mapParament.ContainsKey("START"))
                {
                    e.listErrorCode.Add(new CodeDescription(1, "Command Not Exist"));
                    reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                    return reMote;
                }
                string pPortName = e.mapParament["START"];   // 提取名称
                REMOTE_REPLY_KE rt = SeStart.Invoke(pPortName);
                reMote = (REMOTE_REPLY)rt;
            }
            catch (System.Exception ex)
            {
                // 不存在
                reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                LogRemoteMsg($"ERR -> {ex.Message}");
            }
            return reMote;
        }

        REMOTE_REPLY HandleAcceptWaferID(RemoteCommandHandlerEventArgs e)
        {
            REMOTE_REPLY reMote = REMOTE_REPLY.eCOMMAND_PERFORMED;
            try
            {
                if (!e.mapParament.ContainsKey("ACCWAF") || !e.mapParament.ContainsKey("WAFERID") || !e.mapParament.ContainsKey("MARKID") || !e.mapParament.ContainsKey("WAFERMAPNAME"))
                {
                    e.listErrorCode.Add(new CodeDescription(1, "Command Not Exist"));
                    reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                    return reMote;
                }
                string isAccept = e.mapParament["ACCWAF"];   // 提取名称
                string waferID = e.mapParament["WAFERID"];
                string MarkID = e.mapParament["MARKID"];
                string WaferMapName = e.mapParament["WAFERMAPNAME"];

                //string waferID = "";
                //string MarkID = "";
                //string WaferMapName = "";

                REMOTE_REPLY_KE rt = (REMOTE_REPLY_KE)SeAcceptWafer?.Invoke(isAccept, waferID, MarkID, WaferMapName);
                reMote = (REMOTE_REPLY)rt;
            }
            catch (System.Exception ex)
            {
                // 不存在
                reMote = REMOTE_REPLY.eCOMMAND_PARAMETER_IS_INVALID;
                LogRemoteMsg($"ERR -> {ex.Message}");
            }
            return reMote;
        }

        private ProcessJob CreatePJob(string portName, string recipeName, string lotName)
        {
            ProcessJob pJob;
            pJob = new ProcessJob();
            pJob.pPJobID = $"Port_{portName}_PJob01";
            pJob.pRecipe = recipeName;
            pJob.nPRProcessStart = PrProcessStart.AUTO; 
            pJob.pCarrierID = SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].CarrierID;
            List<int> mapSlotResult = new List<int>();

            if (SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult != null
                && SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult.Count > 0)
            {
                for (int i = 0; i < SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult.Count; i++)
                {
                    if (SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult[i] == 1)
                    {
                        mapSlotResult.Add(i + 1);
                    }
                }
                pJob.listSlot = mapSlotResult;
            }
            else
            {
                LogRemoteMsg("ERR: CreatePJob失败 -> EAP下发工单前设备未上报SlotMap");
                Task.Run(() =>
                {
                    MessageBox.Show("ERR: CreatePJob失败 -> EAP下发工单前设备未上报SlotMap", "提示");
                });
                return null;
            }
            return pJob;
        }
        private ControlJob CreateCJob(ProcessJob pJob, string portName)
        {
            if (pJob == null)
            {
                return null;
            }
            ControlJob cJob;
            cJob = new ControlJob();
            cJob.pCJobID = $"Port_{portName}_CJob01";
            cJob.nStartMethod = ControlJobStart.AUTO;
            ProcessingCtrlSpec processingCtrlSpec = new ProcessingCtrlSpec
            {
                pPRJobID = pJob.pPJobID
            };
            List<ProcessingCtrlSpec> listProcessingCtrlSpec = new List<ProcessingCtrlSpec> { processingCtrlSpec };
            cJob.listProcessingCtrlSpec = listProcessingCtrlSpec;

            return cJob;
        }
        private Carrier CreateCarrierInfo(string portName, string lotName)
        {
            Carrier carrier = new Carrier();
            if (string.IsNullOrEmpty(SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].CarrierID))
            {
                LogRemoteMsg("ERR: CreateCarrierInfo失败 -> EAP下发工单前设备未上报卡匣ID");
                Task.Run(() => { MessageBox.Show("ERR: CreateCarrierInfo失败 -> EAP下发工单前设备未上报卡匣ID", "提示"); });
                return null;
            }
            carrier.pCarrierID = SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].CarrierID;
            carrier.nCarrierIDStatus = CarrierIDStatus.VERIFIED_OK;
            carrier.nSlotMapStatus = CarrierSlotMapStatus.VERIFIED_OK;

            List<string> waferIDList = SeGetWaferIDList?.Invoke($"Port_{portName}");
            for (int i = 0; i < SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult.Count; i++)
            {
                carrier.pSlotData[i].pLotID = lotName;
                carrier.pSlotData[i].pSubstrateID = waferIDList != null ? waferIDList[i] : "";
                if (SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult != null
                && SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult.Count > 0)
                {
                    if (SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult[i] == 0)
                    {
                        carrier.pSlotData[i].nSlotMapEnum = SlotMap.EMPTY;
                    }
                    else if (SecsEquipHelper.LoadPort.MapPort[$"Port_{portName}"].MapSlotResult[i] == 1)
                    {
                        carrier.pSlotData[i].nSlotMapEnum = SlotMap.CORRECTLY_OCCUPIED;
                    }
                }
                else
                {
                    LogRemoteMsg("ERR: CreateCarrierInfo失败 -> EAP下发工单前设备未上报SlotMap");
                    Task.Run(() =>
                    {
                        MessageBox.Show("ERR: CreateCarrierInfo失败 -> EAP下发工单前设备未上报SlotMap", "提示");
                    });
                    return null;
                }
            }
            return carrier;
        }

        private void LogCommMsg(RemoteCommandHandlerEventArgs e)
        {
            string strKeyValue = "";
            if (e.mapParament.Count <= 0)
            {
                strKeyValue = "ERR: 远程命令参数为空";
            }
            else
            {
                foreach (var item in e.mapParament)
                {
                    strKeyValue += string.Format($"{item.Key} = {item.Value}, ");
                }
            }
            LogRemoteMsg(strKeyValue);
        }
        private void LogRemoteMsg(string strMsg)
        {
            LogMsg($"远程命令: {strMsg}", MsgSource_KE.EAP);
        }
    }
}
